package com.cookpad.puree.outputs;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.cookpad.puree.PureeLogger;
import com.cookpad.puree.async.AsyncResult;
import com.cookpad.puree.internal.PureeVerboseRunnable;
import com.cookpad.puree.internal.RetryableTaskRunner;
import com.cookpad.puree.storage.Records;
import java.util.concurrent.ScheduledExecutorService;
import javax.annotation.ParametersAreNonnullByDefault;
@ParametersAreNonnullByDefault
public abstract class PureeBufferedOutput extends PureeOutput {
RetryableTaskRunner flushTask;
ScheduledExecutorService executor;
public PureeBufferedOutput() {
}
@Override
public void initialize(PureeLogger logger) {
super.initialize(logger);
executor = logger.getExecutor();
flushTask = new RetryableTaskRunner(new Runnable() {
@Override
public void run() {
flush();
}
}, conf.getFlushIntervalMillis(), conf.getMaxRetryCount(), executor);
}
@Override
public void receive(final JsonObject jsonLog) {
executor.execute(new PureeVerboseRunnable(new Runnable() {
@Override
public void run() {
JsonObject filteredLog = applyFilters(jsonLog);
if (filteredLog != null) {
storage.insert(type(), filteredLog);
}
}
}));
flushTask.tryToStart();
}
@Override
public void flush() {
executor.execute(new PureeVerboseRunnable(new Runnable() {
@Override
public void run() {
flushSync();
}
}));
}
public void flushSync() {
if (!storage.lock()) {
return;
}
final Records records = getRecordsFromStorage();
if (records.isEmpty()) {
storage.unlock();
return;
}
final JsonArray jsonLogs = records.getJsonLogs();
emit(jsonLogs, new AsyncResult() {
@Override
public void success() {
flushTask.reset();
storage.delete(records);
storage.unlock();
}
@Override
public void fail() {
flushTask.retryLater();
storage.unlock();
}
});
}
private Records getRecordsFromStorage() {
return storage.select(type(), conf.getLogsPerRequest());
}
public abstract void emit(JsonArray jsonArray, final AsyncResult result);
public void emit(JsonObject jsonLog) {
// do nothing
}
}